home *** CD-ROM | disk | FTP | other *** search
- /*
- * lfsLoad.c --
- *
- * Code to handle the loading, checkpoint, and detaching of LFS file
- * system.
- *
- * Copyright 1989 Regents of the University of California
- * Permission to use, copy, modify, and distribute this
- * software and its documentation for any purpose and without
- * fee is hereby granted, provided that the above copyright
- * notice appear in all copies. The University of California
- * makes no representations about the suitability of this
- * software for any purpose. It is provided "as is" without
- * express or implied warranty.
- */
-
- #ifndef lint
- static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/lfs/lfsLoad.c,v 1.10 91/12/17 17:33:48 jhh Exp $ SPRITE (Berkeley)";
- #endif /* not lint */
-
- #include <sprite.h>
- #include <lfsInt.h>
- #include <stdlib.h>
- #include <rpc.h>
-
- #include <string.h>
- #include <lfs.h>
-
- static Fsdm_DomainOps lfsDomainOps = {
- Lfs_AttachDisk,
- Lfs_DetachDisk,
- Lfs_DomainWriteBack,
- Lfs_RereadSummaryInfo,
- Lfs_DomainInfo,
- Lfs_BlockAllocate,
- Lfs_GetNewFileNumber,
- Lfs_FreeFileNumber,
- Lfs_FileDescInit,
- Lfs_FileDescFetch,
- Lfs_FileDescStore,
- Lfs_FileBlockRead,
- Lfs_FileBlockWrite,
- Lfs_FileTrunc,
- Lfs_DirOpStart,
- Lfs_DirOpEnd
- };
-
-
-
- /*
- *----------------------------------------------------------------------
- *
- * LfsLoadFileSystem --
- *
- * Load the checkpointed state of a file system and call the LFS
- * module attach routines to initialize a file system.
- *
- * Results:
- * SUCCESS if the file system was successfully loaded.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- LfsLoadFileSystem(lfsPtr, flags)
- Lfs *lfsPtr; /* File system to load checkpoint state. */
- int flags;
- {
- ReturnStatus status;
- LfsCheckPointHdr checkPointHdr[2], *checkPointHdrPtr;
- LfsCheckPointTrailer *trailerPtr;
- LfsDiskAddr diskAddr;
- int choosenOne, maxSize;
- char *checkPointPtr;
- int checkPointSize;
-
- Sync_LockInitDynamic(&(lfsPtr->checkPointLock), "LfsCheckpointLock");
- /*
- * Examine the two checkpoint areas to locate the checkpoint area with the
- * newest timestamp.
- */
- LfsOffsetToDiskAddr(lfsPtr->superBlock.hdr.checkPointOffset[0],
- &diskAddr);
- status = LfsReadBytes(lfsPtr, diskAddr, sizeof(LfsCheckPointHdr),
- (char *) (checkPointHdr+0));
- if (status != SUCCESS) {
- LfsError(lfsPtr, status, "Can't read checkpoint header #0");
- return status;
- }
- LfsOffsetToDiskAddr(lfsPtr->superBlock.hdr.checkPointOffset[1],
- &diskAddr);
- status = LfsReadBytes(lfsPtr, diskAddr, sizeof(LfsCheckPointHdr),
- (char *) (checkPointHdr+1));
- if (status != SUCCESS) {
- LfsError(lfsPtr, status, "Can't read checkpoint header #1");
- return status;
- }
- choosenOne = (checkPointHdr[0].timestamp<checkPointHdr[1].timestamp) ? 1 : 0;
-
- /*
- * Read in the entire checkpoint region into a buffer.
- */
- maxSize = LfsBlocksToBytes(lfsPtr,
- (lfsPtr->superBlock.hdr.maxCheckPointBlocks));
- checkPointPtr = malloc(maxSize);
-
- again:
- LfsOffsetToDiskAddr(lfsPtr->superBlock.hdr.checkPointOffset[choosenOne],
- &diskAddr);
- status = LfsReadBytes(lfsPtr, diskAddr, maxSize, checkPointPtr);
- if (status != SUCCESS) {
- free((char *) checkPointPtr);
- LfsError(lfsPtr, status, "Can't read checkpoint region");
- return status;
- }
- /*
- * Verify checksum checkpoint region here.
- */
- checkPointHdrPtr = (LfsCheckPointHdr *) checkPointPtr;
- trailerPtr = (LfsCheckPointTrailer *)
- (checkPointPtr + checkPointHdrPtr->size -
- sizeof(LfsCheckPointTrailer));
-
- if (checkPointHdrPtr->timestamp != trailerPtr->timestamp) {
- LfsError(lfsPtr, SUCCESS, "Bad checkpoint timestamps");
- choosenOne = !choosenOne;
- goto again;
- }
-
- /*
- * Install the domain if we can.
- */
- status = Fsdm_InstallDomain(checkPointHdrPtr->domainNumber,
- checkPointHdrPtr->serverID, lfsPtr->name,
- flags, &(lfsPtr->domainPtr));
- if (status != SUCCESS) {
- free((char *) checkPointHdrPtr);
- return (status);
- }
- lfsPtr->domainPtr->backendPtr = LfsCacheBackendInit(lfsPtr);
- lfsPtr->domainPtr->domainOpsPtr = &lfsDomainOps;
- lfsPtr->domainPtr->clientData = (ClientData) lfsPtr;
-
- /*
- * Read in the current stats structure.
- */
- {
- Lfs_StatsVersion1 *statsPtr = (Lfs_StatsVersion1 *)(trailerPtr + 1);
- if (statsPtr->version != 1) {
- printf("LfsLoad: Bad stats version number %d\n", statsPtr->version);
- }
- bcopy ((char *) statsPtr, (char *) &lfsPtr->stats,
- sizeof(lfsPtr->stats));
- }
- checkPointPtr = checkPointPtr + sizeof(LfsCheckPointHdr);
- checkPointSize = ((char *)trailerPtr) - checkPointPtr;
- /*
- * Process the checkpoint for each region by calling segment attach
- * procedures for the modules doing segment I/O.
- */
-
- status = LfsSegAttach(lfsPtr, checkPointPtr, checkPointSize);
-
- if (status != SUCCESS) {
- free((char *) checkPointHdrPtr);
- return status;
- }
-
- /*
- * Setup checkPoint data structure for next checkpoint operation. We use
- * the buffer we allocated and set the nextRegion to be the one we
- * didn't load from. Also set the timestamp into the future.
- */
- lfsPtr->checkPoint.timestamp = checkPointHdrPtr->timestamp+1;
- lfsPtr->checkPoint.nextArea = !choosenOne;
- lfsPtr->checkPoint.buffer = (char *) checkPointHdrPtr;
- lfsPtr->checkPoint.maxSize = maxSize;
-
- /*
- * Fill in the checkPointHdrPtr will the fields that don't change
- * between checkpoints.
- */
- checkPointHdrPtr->timestamp = lfsPtr->checkPoint.timestamp;
- checkPointHdrPtr->size = 0;
- checkPointHdrPtr->version = 1;
- checkPointHdrPtr->domainNumber = lfsPtr->domainPtr->domainNumber;
- checkPointHdrPtr->attachSeconds = Fsutil_TimeInSeconds();
- checkPointHdrPtr->detachSeconds = checkPointHdrPtr->attachSeconds;
- checkPointHdrPtr->serverID = rpc_SpriteID;
-
- return status;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * LfsDetachFileSystem --
- *
- * Detach a file system.
- *
- * Results:
- * SUCCESS if the file system was successfully detach.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- LfsDetachFileSystem(lfsPtr)
- Lfs *lfsPtr; /* File system to load checkpoint state. */
- {
- ReturnStatus status;
-
-
- (*lfsPtr->checkpointIntervalPtr) = 0; /* Stop the timer checkpointer. */
-
- status = LfsCheckPointFileSystem(lfsPtr, LFS_CHECKPOINT_DETACH);
-
- status = LfsSegDetach(lfsPtr);
-
- free(lfsPtr->checkPoint.buffer);
- return status;
- }
- #define LOCKPTR &lfsPtr->checkPointLock
-
-
- /*
- *----------------------------------------------------------------------
- *
- * LfsCheckPointFileSystem --
- *
- * Checkpoint the state of a file system by calling the LFS
- * module attach routines.
- *
- * Results:
- * SUCCESS if the file system was successfully checkpointed.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- LfsCheckPointFileSystem(lfsPtr, flags)
- Lfs *lfsPtr; /* File system to be checkpointed. */
- int flags; /* Flags for checkpoint. */
- {
- LfsCheckPointHdr *checkPointHdrPtr;
- int size, blocks, bytes;
- LfsCheckPointTrailer *trailerPtr;
- LfsDiskAddr diskAddr;
- ReturnStatus status;
- char *bufferPtr;
-
- bufferPtr = lfsPtr->checkPoint.buffer;
- checkPointHdrPtr = (LfsCheckPointHdr *) bufferPtr;
- if (flags & LFS_CHECKPOINT_CLEANER) {
- /*
- * The cleaner uses it own checkpoint buffer. Allocate it
- * and initialized the LfsCheckPointHdr with the values that
- * don't change.
- */
- bufferPtr = malloc(lfsPtr->checkPoint.maxSize);
- bcopy((char *) checkPointHdrPtr, bufferPtr,
- sizeof(LfsCheckPointHdr));
- checkPointHdrPtr = (LfsCheckPointHdr *) bufferPtr;
-
- }
-
-
- status = LfsSegCheckPoint(lfsPtr, flags, (char *)(checkPointHdrPtr+1),
- &size);
- if ((status != SUCCESS) || (size < 0)) {
- if (bufferPtr != lfsPtr->checkPoint.buffer) {
- free(bufferPtr);
- }
- return status;
- }
- LOCK_MONITOR;
- /*
- * Fill in check point header and trailer.
- */
- checkPointHdrPtr->timestamp = LfsGetCurrentTimestamp(lfsPtr);
- checkPointHdrPtr->size = size + sizeof(LfsCheckPointHdr) +
- sizeof(LfsCheckPointTrailer);
- checkPointHdrPtr->version = 1;
- checkPointHdrPtr->detachSeconds = Fsutil_TimeInSeconds();
- trailerPtr = (LfsCheckPointTrailer *)
- (bufferPtr + size + sizeof(LfsCheckPointHdr));
- trailerPtr->timestamp = checkPointHdrPtr->timestamp;
- trailerPtr->checkSum = 0;
-
- /*
- * Append the stats to the checkpoint regions.
- */
- bytes = checkPointHdrPtr->size + sizeof(Lfs_Stats);
- blocks = LfsBytesToBlocks(lfsPtr, bytes);
- LFS_STATS_ADD(lfsPtr->stats.checkpoint.totalBlocks, blocks);
- LFS_STATS_ADD(lfsPtr->stats.checkpoint.totalBytes, bytes);
- bcopy ((char *) &lfsPtr->stats, (char *) (trailerPtr + 1),
- sizeof(lfsPtr->stats));
- LfsOffsetToDiskAddr(
- lfsPtr->superBlock.hdr.checkPointOffset[lfsPtr->checkPoint.nextArea],
- &diskAddr);
- status = LfsWriteBytes(lfsPtr, diskAddr,
- LfsBlocksToBytes(lfsPtr, blocks), (char *) checkPointHdrPtr);
- if (status == SUCCESS) {
- /*
- * Set the file system up to use the other checkpoint buffer next time.
- */
- lfsPtr->checkPoint.nextArea = !lfsPtr->checkPoint.nextArea;
- } else {
- UNLOCK_MONITOR;
- LfsError(lfsPtr, status, "Can't write checkpoint region\n");
- LOCK_MONITOR;
- }
- UNLOCK_MONITOR;
- LfsSegCheckPointDone(lfsPtr, flags);
- if (bufferPtr != lfsPtr->checkPoint.buffer) {
- free(bufferPtr);
- }
- return status;
- }
-
-